home *** CD-ROM | disk | FTP | other *** search
/ Aminet 24 / Aminet 24 (1998)(GTI - Schatztruhe)[!][Apr 1998].iso / Aminet / comm / mail / Mutt089src.lha / Mutt-0.89i-AMIGA / src / pop.c < prev    next >
C/C++ Source or Header  |  1998-01-28  |  7KB  |  317 lines

  1. /*
  2.  * Copyright (C) 1996-8 Michael R. Elkins <me@cs.hmc.edu>
  3.  * 
  4.  *     This program is free software; you can redistribute it and/or modify
  5.  *     it under the terms of the GNU General Public License as published by
  6.  *     the Free Software Foundation; either version 2 of the License, or
  7.  *     (at your option) any later version.
  8.  * 
  9.  *     This program is distributed in the hope that it will be useful,
  10.  *     but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  *     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  *     GNU General Public License for more details.
  13.  * 
  14.  *     You should have received a copy of the GNU General Public License
  15.  *     along with this program; if not, write to the Free Software
  16.  *     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  */ 
  18.  
  19. /*
  20.  * Rather crude POP3 support.
  21.  */
  22.  
  23. #include "mutt.h"
  24.  
  25. #ifdef USE_POP
  26.  
  27. #include "mailbox.h"
  28. #include "mx.h"
  29.  
  30. #include <sys/types.h>
  31. #include <sys/socket.h>
  32. #include <netinet/in.h>
  33. #include <arpa/inet.h>
  34. #include <netdb.h>
  35. #include <string.h>
  36. #include <unistd.h>
  37.  
  38. static int getLine (int fd, char *s, int len)
  39. {
  40.   char ch;
  41.   int bytes = 0;
  42.  
  43.   while (read (fd, &ch, 1) > 0)
  44.   {
  45.     *s++ = ch;
  46.     bytes++;
  47.     if (ch == '\n')
  48.     {
  49.       *s = 0;
  50.       return (bytes);
  51.     }
  52.     /* make sure not to overwrite the buffer */
  53.     if (bytes == len - 1)
  54.     {
  55.       *s = 0;
  56.       return bytes;
  57.     }
  58.   }
  59.   *s = 0;
  60.   return (-1);
  61. }
  62.  
  63. static int getPass (void)
  64. {
  65.   if (!PopPass[0])
  66.   {
  67.     if (mutt_get_password ("POP Password: ", PopPass, sizeof (PopPass)) != 0)
  68.       return 0;
  69.   }
  70.   return 1;
  71. }
  72.  
  73. void mutt_fetchPopMail (void)
  74. {
  75.   struct sockaddr_in sin;
  76. #if SIZEOF_LONG == 4
  77.   long n;
  78. #else
  79.   int n;
  80. #endif
  81.   struct hostent *he;
  82.   char buffer[2048];
  83.   char msgbuf[SHORT_STRING];
  84.   int s, i, msgs, bytes, err = 0;
  85.   CONTEXT ctx;
  86.   MESSAGE *msg = NULL;
  87.  
  88.   if (!PopHost[0])
  89.   {
  90.     mutt_error ("POP host is not defined.");
  91.     return;
  92.   }
  93.  
  94.   if (!PopUser[0])
  95.   {
  96.     mutt_error ("No POP username is defined.");
  97.     return;
  98.   }
  99.     
  100.   if (!getPass ()) return;
  101.  
  102.   s = socket (AF_INET, SOCK_STREAM, IPPROTO_IP);
  103.  
  104.   memset ((char *) &sin, 0, sizeof(sin));
  105.   sin.sin_family = AF_INET;
  106.   sin.sin_port = htons (PopPort);
  107.  
  108.   if ((n = inet_addr (PopHost)) == -1)
  109.   {
  110.     /* Must be a DNS name */
  111.     if ((he = gethostbyname (PopHost)) == NULL)
  112.     {
  113.       mutt_error ("Could not find address for host %s.", PopHost);
  114.       return;
  115.     }
  116.     memcpy ((void *)&sin.sin_addr, *(he->h_addr_list), he->h_length);
  117.   }
  118.   else
  119.     memcpy ((void *)&sin.sin_addr, (void *)&n, sizeof(n));
  120.   
  121.   mutt_message ("Connecting to %s", inet_ntoa (sin.sin_addr));
  122.  
  123.   if (connect (s, (struct sockaddr *) &sin, sizeof (struct sockaddr_in)) == -1)
  124.   {
  125.     mutt_perror ("connect");
  126.     return;
  127.   }
  128.   
  129.   if (getLine (s, buffer, sizeof (buffer)) == -1)
  130.     goto fail;
  131.  
  132.   if (strncmp (buffer, "+OK", 3) != 0)
  133.   {
  134.     mutt_remove_trailing_ws (buffer);
  135.     mutt_error (buffer);
  136.     goto finish;
  137.   }
  138.  
  139.   sprintf (buffer, "user %s\r\n", PopUser);
  140.   write (s, buffer, strlen (buffer));
  141.  
  142.   if (getLine (s, buffer, sizeof (buffer)) == -1)
  143.     goto fail;
  144.  
  145.   if (strncmp (buffer, "+OK", 3) != 0)
  146.   {
  147.     mutt_remove_trailing_ws (buffer);
  148.     mutt_error (buffer);
  149.     goto finish;
  150.   }
  151.   
  152.   sprintf (buffer, "pass %s\r\n", PopPass);
  153.   write (s, buffer, strlen (buffer));
  154.   
  155.   if (getLine (s, buffer, sizeof (buffer)) == -1)
  156.     goto fail;
  157.  
  158.   if (strncmp (buffer, "+OK", 3) != 0)
  159.   {
  160.     PopPass[0] = 0; /* void the given password */
  161.     mutt_remove_trailing_ws (buffer);
  162.     mutt_error (buffer[0] ? buffer : "Server closed connection!");
  163.     goto finish;
  164.   }
  165.   
  166.   /* find out how many messages are in the mailbox. */
  167.   write (s, "stat\r\n", 6);
  168.   
  169.   if (getLine (s, buffer, sizeof (buffer)) == -1)
  170.     goto fail;
  171.  
  172.   if (strncmp (buffer, "+OK", 3) != 0)
  173.   {
  174.     mutt_remove_trailing_ws (buffer);
  175.     mutt_error (buffer);
  176.     goto finish;
  177.   }
  178.   
  179.   sscanf (buffer, "+OK %d %d", &msgs, &bytes);
  180.  
  181.   if (msgs == 0)
  182.   {
  183.     mutt_message ("No new mail in POP mailbox.");
  184.     goto finish;
  185.   }
  186.  
  187.   if (mx_open_mailbox (Spoolfile, M_APPEND, &ctx) == NULL)
  188.     goto finish;
  189.  
  190.   snprintf (msgbuf, sizeof (msgbuf),
  191.         "Reading %d new message%s (%d bytes)...", msgs, msgs > 1 ? "s" : "", bytes);
  192.   mutt_message (msgbuf);
  193.  
  194.   for (i = 1 ; i <= msgs ; i++)
  195.   {
  196.     sprintf (buffer, "retr %d\r\n", i);
  197.     write (s, buffer, strlen (buffer));
  198.  
  199.     if (getLine (s, buffer, sizeof (buffer)) == -1)
  200.     {
  201.       mx_fastclose_mailbox (&ctx);
  202.       goto fail;
  203.     }
  204.  
  205.     if (strncmp (buffer, "+OK", 3) != 0)
  206.     {
  207.       mutt_remove_trailing_ws (buffer);
  208.       mutt_error (buffer);
  209.       break;
  210.     }
  211.  
  212.     if ((msg = mx_open_new_message (&ctx, NULL, M_ADD_FROM)) == NULL)
  213.     {
  214.       err = 1;
  215.       break;
  216.     }
  217.  
  218.     /* Now read the actual message. */
  219.     FOREVER
  220.     {
  221.       char *p;
  222.       int chunk;
  223.  
  224.       if ((chunk = getLine (s, buffer, sizeof (buffer))) == -1)
  225.       {
  226.     mutt_error ("Error reading message!");
  227.     err = 1;
  228.     break;
  229.       }
  230.  
  231.       /* check to see if we got a full line */
  232.       if (buffer[chunk-2] == '\r' && buffer[chunk-1] == '\n')
  233.       {
  234.     if (strcmp(".\r\n", buffer) == 0)
  235.     {
  236.       /* end of message */
  237.       break;
  238.     }
  239.  
  240.     /* change CRLF to just LF */
  241.     buffer[chunk-2] = '\n';
  242.     buffer[chunk-1] = 0;
  243.     chunk--;
  244.  
  245.     /* see if the line was byte-stuffed */
  246.     if (buffer[0] == '.')
  247.     {
  248.       p = buffer + 1;
  249.       chunk--;
  250.     }
  251.     else
  252.       p = buffer;
  253.       }
  254.       else
  255.     p = buffer;
  256.       
  257.       fwrite (p, 1, chunk, msg->fp);
  258.     }
  259.  
  260.     if (mx_close_message (&msg) != 0)
  261.     {
  262.       mutt_error ("Error while writing mailbox!");
  263.       err = 1;
  264.     }
  265.  
  266.     if (err)
  267.       break;
  268.  
  269.     if (option (OPTPOPDELETE))
  270.     {
  271.       /* delete the message on the server */
  272.       sprintf (buffer, "dele %d\r\n", i);
  273.       write (s, buffer, strlen (buffer));
  274.  
  275.       /* eat the server response */
  276.       getLine (s, buffer, sizeof (buffer));
  277.       if (strncmp (buffer, "+OK", 3) != 0)
  278.       {
  279.     err = 1;
  280.         mutt_remove_trailing_ws (buffer);
  281.     mutt_error (buffer);
  282.     break;
  283.       }
  284.     }
  285.  
  286.     mutt_message ("%s [%d messages read]", msgbuf, i);
  287.   }
  288.  
  289.   if (msg)
  290.     mx_close_message (&msg);
  291.   mx_close_mailbox (&ctx);
  292.  
  293.   if (err)
  294.   {
  295.     /* make sure no messages get deleted */
  296.     write (s, "rset\r\n", 6);
  297.     getLine (s, buffer, sizeof (buffer)); /* snarf the response */
  298.   }
  299.  
  300. finish:
  301.  
  302.   /* exit gracefully */
  303.   write (s, "quit\r\n", 6);
  304.   getLine (s, buffer, sizeof (buffer)); /* snarf the response */
  305.   close (s);
  306.   return;
  307.  
  308.   /* not reached */
  309.  
  310. fail:
  311.  
  312.   mutt_error ("Server closed connection!");
  313.   close (s);
  314. }
  315.  
  316. #endif /* USE_POP */
  317.